﻿Imports Microsoft.VisualBasic
Imports System.Security.Cryptography
Imports System.Net



Namespace WebApi
    Namespace Facebook

        Public Class FacebookClient

            Private webClient As WebApi.Net.WebClient

            Public Sub New(oauth2 As WebApi.Oauth.Oauth2)

                Me.webClient = New WebApi.Net.WebClient
                Me.webClient.oAuth2 = oauth2

            End Sub

            Public Property LastError As Net.ServiceError

            Private Function Download(address As String) As String

                Dim res = Encoding.UTF8.GetString(Me.webClient.DownloadData(address))

                webClient.postParams.Clear()

                If Me.webClient.StatusCode <> 200 Then

                    Me.LastError = New Net.ServiceError With {
                        .webClient = Me.webClient,
                        .ResError = res,
                        .Net = WebApi.Type.FACEBOOK
                    }

                    Select Case Me.webClient.StatusCode
                        Case 500, 502, 503, 504
                            'Internal Server Error
                            'Bad Gateway
                            'Service Unavailable
                            'Gateway timeout

                            'Me.LastError = New Net.ServiceError With {.Message = Me.webClient.StatusCodeDescr, .Code = Me.webClient.StatusCode}
                            Me.LastError.Code = Me.webClient.StatusCode
                            Me.LastError.Message = Me.webClient.StatusCodeDescr

                            Net.ExceptionBase.ThrowException(New Net.ExceptionConnectionServer With {.ServiceError = Me.LastError})

                        Case Else

                            Try
                                Dim Err As ServiceErrors
                                Err = MyApp.JSONDeserializeObj(Of ServiceErrors)(res)

                                Me.LastError.Code = Err.error.code
                                Me.LastError.Message = Err.error.message

                            Catch ex As Exception

                                Me.LastError.Code = Me.webClient.StatusCode
                                Me.LastError.Message = res

                            End Try


                            Select Case Me.webClient.StatusCode

                                Case 400
                                    'Unauthorized
                                    Select Case Me.LastError.Code
                                        Case 190
                                            '190 not authorized application
                                            Net.ExceptionBase.ThrowException(New Net.ExceptionAPIAccount With {.ServiceError = Me.LastError})

                                    End Select

                            End Select




                    End Select

                    Net.ExceptionBase.ThrowException(New Net.ExceptionBase With {.ServiceError = Me.LastError})

                End If


                Return res

            End Function

            'Private Sub ThrowException(ex As Net.ExceptionServiceBase)

            '    ex.webclient = Me.webClient
            '    ex.ServiceError = Me.LastError

            '    Dim WebError = SF("client:{0}, {1} - FACEBOOK API ERROR: {2}", Me.webClient.StatusCode, Me.webClient.StatusCodeDescr, Me.LastError.ResError)

            '    ex.Data.Add("ServiceResponse_Error", WebError)
            '    ex.Data.Add("ServiceResponse_URL", Me.webClient.ResponseUri.AbsolutePath)
            '    ex.Data.Add("ServiceResponse_oauthToken", Me.webClient.oAuth2.access_token)

            '    UI.Page.WriteLog(WebError)

            '    Throw ex
            '    'Return ex

            'End Sub
            Public Class ServiceErrors

                Public Property [error] As ServiceError

            End Class
            Public Class ServiceError

                Public Property message As String
                Public Property code As Integer
                Public Property error_subcode As Integer
                Public Property type As String


            End Class
#Region "GENERIC ACCOUNTS FUNCTIONS"

            Public Function GetAccountsLookup(Of tres)(user_id As String, fields As List(Of String)) As Dictionary(Of String, tres)


                Dim Uri As New UriBuilder("https://graph.facebook.com")

                Dim queryString = HttpUtility.ParseQueryString("")

                queryString.Add("ids", user_id)
                queryString.Add("fields", String.Join(",", fields))

                Uri.Query = queryString.ToString


                Dim Res = Me.Download(Uri.Uri.AbsoluteUri)
                'Return Res
                Return MyApp.JSONDeserializeObj(Of Dictionary(Of String, tres))(Res)


            End Function

            Public Function GetAccountConnect(Of tres)(id As String, type As String, fields As List(Of String), since As String, until As String) As Results(Of tres)

                Dim Uri As New UriBuilder(SF("https://graph.facebook.com/{0}/{1}", id, type))

                Dim queryString = HttpUtility.ParseQueryString("")

                queryString.Add("fields", String.Join(",", fields))
                queryString.Add("limit", 200)


                If since <> "" Then
                    queryString.Add("since", since)
                End If
                If until <> "" Then
                    queryString.Add("until", until)
                End If

                Uri.Query = queryString.ToString


                Dim Res = Me.Download(Uri.Uri.AbsoluteUri)
                'Return Res
                Return MyApp.JSONDeserializeObj(Of Results(Of tres))(Res)

            End Function

#End Region

#Region "POST FUNCTIONS"

            Public Function PostPost(status As String, id As String, type As String) As Post

                Dim Uri As New UriBuilder(SF("https://graph.facebook.com/{0}/{1}", id, type))


                Me.webClient.postParams.Add("message", webClient.UrlEncode(status))
                'Me.webClient.postParams.Add("status", status)


                Dim Res = Me.Download(Uri.Uri.AbsoluteUri)

                Return MyApp.JSONDeserializeObj(Of Post)(Res)
                'Dim Res As String = ""
                'Res = Me.webClient.DownloadString(Uri.Uri.AbsoluteUri)

            End Function


#End Region


#Region "USER FUNCTIONS"

            Public Function GetCurrUser() As User

                Return Me.GetCurrUser(User.DefFields)

            End Function
            Public Function GetCurrUser(fields As List(Of String)) As User

                Dim Uri As New UriBuilder("https://graph.facebook.com/me")

                Dim queryString = HttpUtility.ParseQueryString("")

                queryString.Add("fields", String.Join(",", fields))

                'If screen_name <> "" Then
                '    queryString.Add("screen_name", screen_name)
                'Else
                '    queryString.Add("user_id", user_id)
                'End If

                Uri.Query = queryString.ToString


                Dim Res = Me.Download(Uri.Uri.AbsoluteUri)
                'Return Res
                Return MyApp.JSONDeserializeObj(Of User)(Res)


            End Function

            Public Function GetUsersLookup(user_id As String) As Dictionary(Of String, User)

                Return Me.GetAccountsLookup(Of User)(user_id, User.DefFields)

            End Function


#End Region




#Region "PAGE FUNCTIONS"

            Public Function GetPagesLookup(user_id As String) As Dictionary(Of String, Page)

                Return Me.GetAccountsLookup(Of Page)(user_id, Page.DefFields)

            End Function

            Public Function GetPageFeed(id As String, since As String, until As String) As Results(Of Post)

                Return GetAccountConnect(Of Post)(id, "feed", Post.DefPageFeedFields, since, until)

            End Function


#End Region

#Region "SEARCH FUNCTIONS"

            Public Function GetSearchPost(q As String, since As String, until As String) As Results(Of Post)


                Return GetSearch(Of Post)(q, "post", Post.DefSearchFields, since, until)


            End Function

            Public Function GetSearch(Of tres)(q As String, type As String, fields As List(Of String), since As String, until As String) As Results(Of tres)

                Dim Uri As New UriBuilder(SF("https://graph.facebook.com/search"))

                Dim queryString = HttpUtility.ParseQueryString("")

                queryString.Add("q", q)
                queryString.Add("type", type)
                queryString.Add("fields", String.Join(",", fields))
                queryString.Add("limit", 100)

                If since <> "" Then
                    queryString.Add("since", since)
                End If
                If until <> "" Then
                    queryString.Add("until", until)
                End If

                Uri.Query = queryString.ToString


                Dim Res = Me.Download(Uri.Uri.AbsoluteUri)

                'Dim o = MyApp.JSONDeserialize(Res)

                'Return o("data")

                Return MyApp.JSONDeserializeObj(Of Results(Of tres))(Res)


            End Function

#End Region




        End Class

        Public Class Results(Of tres)

            Public Property data As New List(Of tres)

            Public Property paging As ResultPaging

            Public Property count As Integer

        End Class

        Public Class Result(Of tres)

            Public Property data As tres


        End Class

        Public Class ResultPaging

            Public Property previous As String
            Public Property [next] As String

        End Class


        Public Class User



            Public Property id As String
            Public Property name As String
            'Public Property first_name As String
            'Public Property middle_name As String
            'Public Property last_name As String
            Public Property link As String
            Public Property username As String
            Public Property gender As String
            Public Property bio As String

            Public Property location As Location

            Public Property picture As Result(Of Picture)

            Public Property accounts As Results(Of Account)

            Public Shared Function DefFields() As List(Of String)

                Return New List(Of String) From {
                    "name", "link", "username", "location", "gender", "bio",
                    "picture", "accounts"
                }

            End Function
            'Public Shared Function DefFieldsLookup() As List(Of String)

            '    Return New List(Of String) From {
            '        "name", "link", "username", "location",
            '        "picture", "accounts"
            '    }

            'End Function

            'accounts

        End Class
        Public Class Page

            Public Property id As String
            Public Property about As String
            Public Property name As String
            Public Property link As String
            Public Property likes As Integer
            Public Property username As String

            Public Property location As Location

            Public Property picture As Result(Of Picture)

            Public Shared Function DefFields() As List(Of String)

                Return New List(Of String) From {
                    "about", "name", "link", "location", "likes", "username",
                    "picture"
                }

            End Function
        End Class

        Public Class Post

            Public Property id As String
            Public Property message As String
            Public Property story As String
            Public Property created_time As Date

            Public Property from As From
            Public Property likes As Results(Of [Like])
            Public Property comments As Results(Of Comment)

            Public Property type As String

            Public Shared Function DefSearchFields() As List(Of String)

                Return New List(Of String) From {
                    "message"
                }

            End Function

            Public Shared Function DefPageFeedFields() As List(Of String)

                Return New List(Of String) From {
                    "message", "from", "likes", "comments", "type", "story"
                }

            End Function

        End Class

        Public Class From

            Public Property id As String
            Public Property name As String
            Public Property category As String


        End Class

        Public Class [Like]

            Public Property id As String
            Public Property name As String

        End Class

        Public Class Comment

            Public Property id As String
            Public Property from As From
            Public Property message As String
            Public Property created_time As Date


        End Class


        'Public Class Accounts

        '    Public Property Data As New List(Of Account)

        'End Class
        Public Class Account

            Public Property id As String
            Public Property category As String
            Public Property access_token As String
            Public Property Name As String

        End Class

        Public Class Location

            Public Property id As String
            Public Property name As String

        End Class

        'Public Class PictureData

        '    Public Property Data As Picture

        'End Class
        Public Class Picture

            Public Property url As String

        End Class


    End Namespace
End Namespace